package main

import "fmt"

func main() {
	array := [5]int{1, 2, 3, 4, 5}
	mySlice := array[1:3]
	fmt.Printf("mySlice %+v\n", mySlice)
	fullSlice := array[:]
	remove3rdItem := deleteItem(fullSlice, 2)

	fmt.Printf("remove3rdItem %+v\n", remove3rdItem) // [1 2 4 5]
	fmt.Printf("fullSlice %+v\n", fullSlice)         // [1 2 4 5 5]
	fmt.Printf("array %+v\n", array)                 // [1 2 4 5 5]
	// 由此可见，是在原来的内存位置做修改的

	s1 := []int{1, 2, 3, 4} //  4 个元素的切片  怎么看切片和数组？前面那个方括号没数字的就是切片，有就是数组
	fmt.Printf("s1: %v, len %d, cap: %d \n", s1, len(s1), cap(s1))

	s2 := make([]int, 3, 4) // 三个元素， 容量为4
	fmt.Printf("s2: %v, len %d, cap %d \n", s2, len(s2), cap(s2))

	s2 = append(s2, 1) // 后边添加一个元素，没有超出容量限制，不会发生扩容
	fmt.Printf("s2: %v, len %d, cap: %d \n", s2, len(s2), cap(s2))

	s2 = append(s2, 2) // 后边添加了一个元素，触发扩容
	fmt.Printf("s2: %v, len %d, cap: %d \n", s2, len(s2), cap(s2))

	slice := []int{1, 2, 3, 4, 5}
	for _, value := range slice {
		value += 2 // 不生效的，for-range的value其实是原来值的拷贝，所以不生效
	}
	fmt.Printf("slice %+v\n", slice)
	for index, _ := range slice {
		slice[index] += 2 // 这样才生效
	}
	fmt.Printf("slice %+v\n", slice)

	slice1 := new([]int)
	slice2 := make([]int, 0)
	slice3 := make([]int, 10)     // 10个元素 容量也为10
	slice4 := make([]int, 10, 20) // 10个元素 容量为20
	fmt.Printf("slice1 %+v\n", slice1)
	fmt.Printf("slice2 %+v\n", slice2)
	fmt.Printf("slice3 %+v\n", slice3)
	fmt.Printf("slice4 %+v\n", slice4)

	ShareSlice()
	test()
	test2()
}

// 删除切片某个位置的元素
func deleteItem(slice []int, index int) []int {
	return append(slice[:index], slice[index+1:]...)
}

func ShareSlice() {
	fmt.Println("******************ShareSlice******************")
	s1 := []int{1, 2, 3, 4, 5, 6}
	s2 := s1[2:]
	fmt.Printf("s1: %v, len %d, cap: %d \n", s1, len(s1), cap(s1))
	fmt.Printf("s2: %v, len %d, cap: %d \n", s2, len(s2), cap(s2))

	s2[0] = 99 // 是共享的，s2改了，s1也改
	fmt.Printf("s1: %v, len %d, cap: %d \n", s1, len(s1), cap(s1))
	fmt.Printf("s2: %v, len %d, cap: %d \n", s2, len(s2), cap(s2))

	s2 = append(s2, 199) // append之后就会生成一个新的了(这句话错了，eg: test())
	fmt.Printf("s1: %v, len %d, cap: %d \n", s1, len(s1), cap(s1))
	fmt.Printf("s2: %v, len %d, cap: %d \n", s2, len(s2), cap(s2))

	s2[1] = 1999 // 这是s2再改了s1就不会改了
	fmt.Printf("s1: %v, len %d, cap: %d \n", s1, len(s1), cap(s1))
	fmt.Printf("s2: %v, len %d, cap: %d \n", s2, len(s2), cap(s2))

	s3 := []int{1, 2, 3, 4}
	dd := make([]int, len(s3))
	copy(dd, s3)
	s4 := append(dd[:0], dd[1:]...)
	fmt.Printf("s3: %v\n", s3)
	fmt.Printf("s4: %v\n", s4)
}

func test() {
	fmt.Println("******************test******************")

	var slice = []int{1, 2, 3, 4, 5} // len:5,capacity:5
	fmt.Println(&slice)

	// 容量之所以为4是因为，原来slice的下标1后面有四位，若slice=[]int{1,2,3,4,5,6}的话，同理则容量为5
	var newSlice = slice[1:3]    // len:2,capacity:4   (已经使用了两个位置，所以还空两位置可以append),
	fmt.Printf("%p\n", slice)    //0xc420098000
	fmt.Printf("%p\n", newSlice) //0xc420098008 可以看到newSlice的地址指向的是slice[1]的地址，即他们底层使用的还是一个数组
	fmt.Printf("%v\n", slice)    //[1 2 3 4 5]
	fmt.Printf("%v\n", newSlice) //[2 3]

	newSlice[1] = 9              //更改后slice、newSlice都改变了
	fmt.Printf("%v\n", slice)    // [1 2 9 4 5]
	fmt.Printf("%v\n", newSlice) // [2 9]

	//dd := append(newSlice,11,12)
	newSlice = append(newSlice, 11, 12) //append 操作之后，slice的len和capacity不变,newSlice的len变为4，capacity：4。因为这是对newSlice的操作
	fmt.Printf("%v\n", slice)           //[1 2 9 11 12] //注意对newSlice做append操作之后，slice[3],slice[4]的值也发生了改变
	fmt.Printf("%v\n", newSlice)        //[2 9 11 12]
	//fmt.Printf("%v\n",dd)

	newSlice = append(newSlice, 13, 14) // 因为newSlice的len已经等于capacity，所以再次append就会超过capacity值，
	// 此时，append函数内部会创建一个新的底层数组（是一个扩容过的数组），并将slice指向的底层数组拷贝过去，然后在追加新的值。
	fmt.Printf("%p\n", slice)    //0xc420098000
	fmt.Printf("%p\n", newSlice) //0xc4200a0000
	fmt.Printf("%v\n", slice)    //[1 2 9 11 12]
	fmt.Printf("%v\n", newSlice) //[2 9 11 12 13 14]  他两已经不再是指向同一个底层数组了
}

func test2() {
	fmt.Println("******************test2******************")
	var slice = []int{1, 2, 3, 4, 5}
	fmt.Printf("slice: %v, len %d, cap: %d, address: %p\n", slice, len(slice), cap(slice), slice)
	//slice: [1 2 3 4 5], len 5, cap: 5, address: 0xc0000c01e0

	ints := append(slice[:2], slice[3:]...)
	fmt.Printf("ints: %v, len %d, cap: %d, address: %p\n", ints, len(ints), cap(ints), ints)
	//ints: [1 2 4 5], len 4, cap: 5, address: 0xc0000c01e0

	fmt.Printf("slice: %v, len %d, cap: %d, address: %p\n", slice, len(slice), cap(slice), slice)
	//slice: [1 2 4 5 5], len 5, cap: 5, address: 0xc0000c01e0

	// 三个的地址其实是一样的，就是说当我做了append(slice[:2], slice[3:]...)这个操作后，要使用ints,不能使用slice了
}
